Skip to content

Rename prohibitAllSharing to containsRestrictedData - #234

Draft
Maximo-Guk wants to merge 4 commits into
bigquery-public-datafrom
restricted-data-rename
Draft

Rename prohibitAllSharing to containsRestrictedData#234
Maximo-Guk wants to merge 4 commits into
bigquery-public-datafrom
restricted-data-rename

Conversation

@Maximo-Guk

@Maximo-Guk Maximo-Guk commented Aug 17, 2026

Copy link
Copy Markdown
Member

Old model: prohibitAllSharing blocked all sharing the moment sensitive data was observed. No one other than the owner could access a latched workspace.

New model: containsRestrictedData allows sharing but requires per-collaborator observer verification against each gatekeeper that read sensitive data. The workspace still goes into a restricted mode (no actions against gatekeepers, no web fetches), but collaborators can open it if they pass verification.

WIP

@github-actions github-actions Bot added workshop/frontend Changes to the Workshop frontend kernel Changes to the Workshop kernel gatekeeper Changes to a gatekeeper integration workshop/shared Changes to shared Workshop APIs labels Aug 17, 2026
@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch from c04d5e3 to aa71300 Compare August 17, 2026 03:45
@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch from cf3449d to f633a1a Compare August 17, 2026 13:17
@Maximo-Guk
Maximo-Guk force-pushed the maximo/pr-previews branch 6 times, most recently from 5f1ff10 to e4e661c Compare August 17, 2026 22:55
Base automatically changed from maximo/pr-previews to main August 17, 2026 22:59
@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch from f633a1a to bc6f07a Compare August 18, 2026 14:34
@github-actions

Copy link
Copy Markdown

Preview: pr234-restricted-data-rename

https://pr234-restricted-data-rename-router.cloudflare-os-previews.workers.dev

Dashboard · deleted when this PR closes

@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch 2 times, most recently from 413e955 to b2c3e58 Compare August 18, 2026 16:38
@Maximo-Guk
Maximo-Guk marked this pull request as ready for review August 18, 2026 16:55
@Maximo-Guk
Maximo-Guk marked this pull request as draft August 18, 2026 16:55
devin-ai-integration[bot]

This comment was marked as resolved.

@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch 2 times, most recently from cd22d16 to b7c9372 Compare August 19, 2026 16:04
devin-ai-integration[bot]

This comment was marked as resolved.

@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch from 41ae6a0 to 740374a Compare August 19, 2026 19:52

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment thread packages/workshop-backend/src/overseer.ts Outdated

const isOwner = !metadata.owner
const sharingProhibited = metadata.sharingProhibited === true
const containsRestrictedData = metadata.containsRestrictedData === true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Kernel and UI changes are shipped in the same commits, against the repository's review rule

The change edits the kernel and the browser UI together in single commits (packages/workshop-frontend/src/ShareModal.tsx:374 alongside packages/workshop-backend/src/overseer.ts), so the kernel cannot be reviewed apart from the UI as the repository requires.
Impact: Reviewers cannot review the security-critical kernel diff independently, which the project's review policy mandates.

Rule and commit layout

REVIEW.md ("High-scrutiny areas"): "A large kernel change should be split by concern into separate PRs, and at minimum grouped into commits that let workshop-backend/workshop-shared be reviewed apart from UI. Flag PRs that bundle both."

Commits 6b778a1 and 1991473 each touch packages/workshop-backend/src/overseer.ts, packages/workshop-shared/src/api.ts, packages/workshop-shared/src/gatekeeper.ts and packages/workshop-frontend/src/ShareModal.tsx in one commit.

Prompt for agents
Per REVIEW.md, kernel changes (packages/workshop-backend, packages/workshop-shared) must be reviewable apart from UI changes. Restructure the history so the ShareModal.tsx (workshop-frontend) edits live in their own commit(s) separate from the overseer.ts/api.ts/gatekeeper.ts changes, or split the frontend change into its own PR.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +2996 to +3011
vendorId !== null && this.#inScopeGatekeepers("use").some(gk => gk.id === gatekeeperId);

for (let collaborator of collaborators) {
// A verifiable gatekeeper outside a "use" collaborator's scope is one the UI can't invoke
// and ensureObserver can't cover; only the unverifiable case above blocks regardless of
// role. An absent role means "build" (see CollaboratorInfo), which fails safe here.
if (vendorId && (collaborator.role ?? "build") === "use" && !inUseScope) continue;
let observer = vendorId ? this.storage.observers.get(collaborator.profile.id) : undefined;
if (!observer || !(gatekeeperId in observer.accountChoices)) {
throw new Error(
"This observation was blocked because it contains sensitive data, but this " +
`workspace is shared with ${collaborator.profile.name} (${collaborator.profile.id}), ` +
"who has not been verified to have access to that data. They must re-open the " +
"workspace (which verifies their access) or be removed from it before this data " +
"can be read.");
}

@devin-ai-integration devin-ai-integration Bot Aug 19, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 A "use" collaborator can now open a workspace holding restricted data without being verified against the connection that read it

Removing the wholesale block in open() (packages/workshop-backend/src/overseer.ts:6751-6756) means a non-owner may now open a workspace that has observed containsRestrictedData, and verification is only run for gatekeepers in their role's scope. For a use collaborator, #inScopeGatekeepers("use") (packages/workshop-backend/src/overseer.ts:6091-6112) only includes connections bound by a non-pending gadget, so a connection that read restricted data through the agent's chat bindings only (never bound to a gadget) is never verified against them, and the observation-time coverage guard explicitly skips them for that connection (packages/workshop-backend/src/overseer.ts:3002). If the agent persists that restricted data into gadget code/storage, the use collaborator renders it through the gadget UI with no access check at all — previously impossible, since a latched workspace refused every non-owner open.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

devin-ai-integration[bot]

This comment was marked as resolved.

@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from ask-bonk Bot Aug 19, 2026
@cloudflare cloudflare deleted a comment from github-actions Bot Aug 19, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment thread packages/workshop-backend/src/overseer.ts Outdated
Comment on lines +3018 to +3024
throw new Error(
"This observation was blocked because it contains sensitive data, but this " +
`workspace is shared with ${collaborator.profile.name}, ` +
"who has not been verified to have access to that data. They must re-open the " +
"workspace (which verifies their access) or be removed from it before this data " +
"can be read.");
}

@devin-ai-integration devin-ai-integration Bot Aug 20, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Blocked sensitive read names a collaborator to sandboxed gadget and agent output

The coverage-guard error embeds collaborator.profile.name (packages/workshop-backend/src/overseer.ts:3020) and, as its own comment notes, this message is surfaced to sandboxed gadget code and agent output — an audience that cannot otherwise enumerate collaborators. The comment claims the profile id is omitted because it is "often an email address", but profile.name is the user-supplied display name and, for password signups, is set to the username/email (see createAccount(username, username, ...) usage), so the identifier the guard intends to withhold can still be exposed.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch 3 times, most recently from 108a748 to 9d7c2fe Compare August 21, 2026 05:12
@github-actions github-actions Bot added the delivery Changes to CI or release delivery label Aug 21, 2026
@Maximo-Guk
Maximo-Guk changed the base branch from main to bigquery-public-data August 21, 2026 05:12
@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch from 9d7c2fe to d3095c6 Compare August 21, 2026 20:16
@github-actions github-actions Bot removed the delivery Changes to CI or release delivery label Aug 21, 2026
Maximo-Guk and others added 4 commits August 21, 2026 15:27
Rename prohibitAllSharing to containsRestrictedData: the flag now means
"this observation carries data whose sharing is governed by observer
verification" rather than a wholesale ban on sharing the workspace. The
legacy flag is still read on persisted records and converted on load.

Instead of refusing to share a flagged workspace outright, sharing is
admitted when every collaborator is verified as an observer of the
producing gatekeeper:

- open() verifies each collaborator against every gatekeeper in their
  role's verification scope (ensureObserver), and the coverage guard
  (#assertSensitiveObservationCoverage) blocks a sensitive observation
  naming any current collaborator not yet verified against its
  producer. Coverage is held to each collaborator's role scope, since a
  "use" collaborator can never be verified against a gatekeeper no
  gadget binds.
- Share-key redemption writes a *pending* edge that grants no interim
  authority: the redeeming open() verifies the recipient at the role
  the edge would grant, confirms only on success (capped at the
  verified role, denied if the connection/binding topology changed
  mid-verification, merged if a concurrent redemption landed first),
  and rolls the edge back on refusal or a null effective role.
- Removing the producing connection no longer lifts the restriction
  for existing collaborators, and assertNewSharingAllowed refuses new
  grants inside the grant write's synchronous block.
- The coverage-guard error reaches sandboxed gadget/agent output, so
  it names the collaborator but omits their profile id (the full email
  on OAuth/CF Access deployments).

Three hardening rounds are folded in:

- A failed live re-check scrubs the failed gatekeeper from the
  collaborator's persisted observer record synchronously with the
  failure determination (covering both failure sites and
  cancel-after-reprompt), and the terminal catch best-effort
  de-registers invalidated gatekeepers alongside newly-added ones
  (removeObserver is idempotent). Without this, a collaborator whose
  provider-side access was revoked kept admitting the producer's
  restricted observations to their still-live older session. The scrub
  is scoped to the failed gatekeeper; a repaired pass re-persists full
  coverage. Fail-closed by design: an operational failure (outage,
  expired credential) scrubs the same way, blocking that producer's
  restricted reads until the collaborator re-opens successfully.

- confirmShareKeyRedemption re-asserts the redemption policy via the
  same optional assertGrantAllowed callback the other grant-writing
  mutators use, in the granting write's synchronous block: redemption
  is two-phase, and a restricted-data producer removed between the
  pending write and the confirm -- invisible to the topology
  fingerprint, since an unverifiable legacy producer's remove() skips
  the share-link guard -- must still refuse the grant. An
  already-confirmed edge skips it, matching redeemShareKey.

- The accepted pending-edge re-add wart is documented precisely: a
  racing removal necessarily aimed at a previously confirmed edge
  (pending-only recipients are invisible to listCollaborators), the
  re-add carries no incremental authority (the recipient holds the
  live, manually re-redeemable link), and revoking the link is the
  durable exclusion.

The accepted residuals (formerly-bound and never-bound producers
outside "use" scope) are documented in docs/observers.md edge case 4
and docs/sharing.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e scope

New sensitive-observations and observer-role-scope suites, with the
harness, RPC client, and gatekeeper-test fixture support they need
(the fixture gains a configurable observer hook and sensitive reads).

The fixture's verify outcome can also target a single bound resource
(a resource-specific key with a label-wide fallback), which the
coverage-scrub test uses to prove the scrub is per-producer: after a
failed re-verification, exactly the refused producer's restricted
reads are blocked -- the sibling producer's keep flowing -- until a
repaired re-open re-persists coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Update gatekeeper-google to the renamed flag, and revise the
gatekeeper-mcp README and write-gatekeeper skill guidance to describe
observer-verified sharing rather than a wholesale sharing prohibition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The modal no longer refuses to share a workspace with restricted data;
it explains that collaborators must be verified against the producing
connection at their next open. The share key is retained across
failures and reloads (sessionStorage tier) so a recipient who is
denied verification can retry, and is discarded at the first
successful open so a later removal isn't undone by an automatic
re-redemption.

The sessionStorage tier lives in retainedShareKeys.ts (so useAuth does
not import the workspace hook) and is bound to the user who captured
the key, so it cannot cross users in a shared tab:

- Entries are identity-stamped (JSON {key, userId}) with the capturing
  session's whoami, resolved from the same stub the open is issued on.
  The retained-read path honors an entry only when the current
  session's identity matches; a definite mismatch sweeps it, a
  transport failure leaves it but does not attach the key. The common
  keyless open stays fully pipelined -- identity is only resolved when
  a fragment key is captured (async, gated against the success-discard
  racing it) or a stored entry exists (rare: only after a reload
  mid-retry). Malformed or unstamped entries read as absent.
- logout() sweeps the whole retention prefix, before the CF Access
  navigate-away.

The in-memory ref tier needs no stamp: it is bounded by the editor's
lifetime (logout unmounts it; CF Access logout navigates away).
Residual: a reload before the identity stamp lands loses retention,
recovered by re-clicking the invite link.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Maximo-Guk
Maximo-Guk force-pushed the bigquery-public-data branch from a2c035d to cbfaf39 Compare August 21, 2026 20:33
@Maximo-Guk
Maximo-Guk force-pushed the restricted-data-rename branch from d3095c6 to d120690 Compare August 21, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gatekeeper Changes to a gatekeeper integration kernel Changes to the Workshop kernel workshop/frontend Changes to the Workshop frontend workshop/shared Changes to shared Workshop APIs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant